#ifndef NETSTACK_H
#define NETSTACK_H

#include <stdbool.h>

#define BUFFER_SIZE 312
uint8_t buffer[BUFFER_SIZE];

//Ethernet Header types bytorder reversed for little endian mc
#define TYPE_ARP 0x0608		// 0x0806 big endian 
#define TYPE_IP 0x0008  	// 0x0800 big endian	


//IP Header types
#define IPTYPE_UDP 0x11
#define IPTYPE_TCP 0x06
#define IPTYPE_ICMP 0x01

//ARP Opcode
#define ARP_REQUEST 0x01
#define ARP_RESPONSE 0x02

//ICMP Types
#define ICMP_REQUEST 0x08
#define ICMP_REPLAY 0x00


//Buffer Positions
#define TCP_HEADERPOS 34
#define TCP_HEADERLENGTH 20
#define TCP_options (20 + TCP_HEADERPOS);

#define IP_HEADERLENGTH 20
#define IP_HEADERPOS 14

#define UDP_HEADERLENGTH 8
#define UDP_HEADERPOS 34
#define UDP_DATAPOS 42

#define ARP_HEADERPOS 14

//TCP Flag Position
#define	TCP_URG 5
#define TCP_ACK 4
#define TCP_PSH 3
#define TCP_RST 2
#define	TCP_SYN 1
#define TCP_FIN 0


//TCP PORTS
#define PORT_TELNET 23
#define PORT_HTTP	80

typedef struct ARP_alloc
{
	uint8_t mac_addr[6];
	uint8_t ip_addr[4];
} arp_alloc;



/* HEADER */

typedef struct ETH_header
{
	uint8_t ETH_destmac[6];
	uint8_t ETH_sourcemac[6];
	uint16_t ETH_type;
} eth_header;


/*ARP defheader:	hardware type - Ethernet 0x0001
					protocol type - IP 0x0800 
					hardware size - 0x06
					protocol size - 0x04			*/				 
#define ARP_DEFHEADER { 0x0100, 0x0008, 0x06, 0x04, 0x00 }

typedef struct ARP_defheader
{
	uint16_t	hwtype;
	uint16_t	protocol;
	uint8_t		hwlen;
	uint8_t		protolen;
	uint8_t		opcode;
} arp_defheader;


typedef struct ARP_header
{
	uint8_t		ARP_opcode;
	uint8_t 	ARP_sourcemac[6];
	uint8_t		ARP_sourceip[4];
	uint8_t		ARP_destmac[6];
	uint8_t		ARP_destip[4];	
} arp_header;

/* IP header	version/headerl	- 0x45
				diff service	- 0x00
				total length 	- 0x0000	header + payload
				identification	- 0x0000
				fragmet offset 	- 0x4000
				ttl				- 0x40			*/

#define IP_DEFHEADER { 0x45, 0x00, 0x0000, 0x0000, 0x0040, 0x40 }

struct IP_defheader
{
	uint8_t		vhl;
	uint8_t		tos;
	uint16_t	IP_len;
	uint16_t	id;
	uint16_t	offset;
	uint8_t		ttl;
};

struct IP_header
{
	uint8_t		IP_protocol;
	uint16_t	IP_chksum;
	uint8_t		IP_sourceip[4];
	uint8_t		IP_destip[4];
};

struct ICMP_header
{
	uint8_t		ICMP_type;
	uint8_t		ICMP_code;
	uint16_t	ICMP_chksum;
	uint16_t	ICMP_id;
//	uint16_t	seqno;
};


struct UDP_pheader
{
	uint8_t srcip[4];
	uint8_t destip[4];
	uint8_t pad;
	uint8_t protocol;
	uint16_t udp_dlen;	
};

struct UDP_header
{
	uint16_t UDP_srcport;
	uint16_t UDP_destport;
	uint16_t UDP_len;
	uint16_t UDP_chksum;
};


struct TCP_pheader
{
	uint8_t srcip[4];
	uint8_t destip[4];
	uint8_t zero;
	uint8_t protocol;
	uint16_t tcplen;
};

#define TCP_ostart 20

struct TCP_socket
{
	bool state;
	uint16_t srcport;
	uint16_t destport;
	uint32_t ack_counter;
	uint32_t seq_counter;
	uint8_t next;
};


struct TCP_header
{
        uint16_t TCP_srcport;
        uint16_t TCP_destport;

//		uint32_t TCP_seqnumber;
//		uint32_t TCP_acknumber;

        uint16_t TCP_seqnumber_p1;
        uint16_t TCP_seqnumber_p2;
        uint16_t TCP_acknumber_p1;
        uint16_t TCP_acknumber_p2;

/*      Data Offset (4 Bit)
        Reserved (6 Bit) NULL
        bool TCP_urg;
        bool TCP_ack;
        bool TCP_psh;
        bool TCP_rst;
        bool TCP_syn;
        bool TCP_fin;
*/      uint8_t TCP_len;
        uint8_t TCP_flags;

        uint16_t TCP_window;
        uint16_t TCP_chksum;
        uint16_t TCP_urgp;
//  Options (0-40 Byte)
};




void net_init(void);
void net_handle(void);
void arp_response(struct ETH_header*, struct ARP_header*, uint16_t);
bool check_arpbc(uint8_t*);

#endif
